#include "pongServer.h"

///////////////////////////////////////////////////
// This function initualizes the games variables //
///////////////////////////////////////////////////

void init_gameState( GS *gs )
{
	gs->ball_x = (float)( SCREEN_WIDTH / 2 );
	gs->ball_y = (float)( SCREEN_HEIGHT / 2 );
	gs->paddle_x[0] = 0;
	gs->paddle_x[1] = (float)( SCREEN_WIDTH - PADDLE_WIDTH );
	gs->paddle_y[0] = (float)( SCREEN_HEIGHT / 2 );
	gs->paddle_y[1] = (float)( SCREEN_HEIGHT / 2 );
}

int server()
{
	/////////////////////////////////
	// We initialize the gameState //
	/////////////////////////////////
	GS gameState;
	init_gameState( &gameState );

	/////////////////////////////////////////////////////////////////
	// This is where we setup our connections with the two clients //
	/////////////////////////////////////////////////////////////////

	// create a tcp socket for the server to listen
	sf::SocketTCP listener;
	
	if( !listener.Listen( PORT ) )
	{ return EXIT_FAILURE; }

	std::cout << "waiting for 2 clients to connect" << std::endl;	

	sf::IPAddress clientAddresses[2];
	sf::SocketTCP clients[2];

	// accept two clients to listen from for the pong game
	if (listener.Accept(clients[0], &clientAddresses[0]) != sf::Socket::Done)
	{return EXIT_FAILURE;}
    std::cout << "Client 0 connected : " << clientAddresses[0] << std::endl;

	if (listener.Accept(clients[1], &clientAddresses[1]) != sf::Socket::Done)
	{return EXIT_FAILURE;}
    std::cout << "Client 1 connected : " << clientAddresses[1] << std::endl;

	//sf::RenderWindow FPS( sf::VideoMode( 800, 600 ), "Server" );
	//FPS.SetFramerateLimit( 60 );

	// after the connections are made we can unblock them.
	listener.SetBlocking( false );
	clients[0].SetBlocking( false );
	clients[1].SetBlocking( false );

	//this contiuouly sends the game state.
	sf::Packet paddleDirection[2];

	/////////////////////////////////////////////////////////////////////
	// Here are the servers ball postion variabls and paddle variables //
	/////////////////////////////////////////////////////////////////////

	float ball_x = 400.f;
	float ball_y = 300.f;
	float ball_Xdelta = (float)BALL_SPEED;
	float ball_Ydelta = (float)BALL_SPEED;
	float paddle_y[2];
	short clientDirection[2] = { 0, 0 };
	
	paddle_y[0] = (float)( SCREEN_HEIGHT / 2 );
	paddle_y[1] = (float)( SCREEN_HEIGHT / 2 );

	while(1)
	{

		//////////////////////////////////////////////////
		// This is where the client information is sent //
		//////////////////////////////////////////////////

		
		for( int i = 0; i < 2; i++ )
		{
			//client 0 sends it's direction '1' = up '2' = down '0' = stopped
			while( clients[i].Receive( paddleDirection[i] ) != sf::Socket::NotReady )
			{
				paddleDirection[i] >> clientDirection[i];
				// TESTING: seeing if the clients are sending things
				std::cout << "client 0 input: " << clientDirection[i] << std::endl;
			}
			if( clientDirection[i] == 1 )
			{
				paddle_y[i] -= (float)PADDLE_SPEED;
			}
			if( clientDirection[i] == 2 )
			{
				paddle_y[i] += (float)PADDLE_SPEED;
			}
			if( clientDirection[i] == 0 )
			{
				paddle_y[i] += 0;
			}
			if( paddle_y[i] < 0 )
			{
				paddle_y[i] = 0;
			}
			if( paddle_y[i] > SCREEN_HEIGHT - PADDLE_HEIGHT)
			{
				paddle_y[i] = (float)SCREEN_HEIGHT - PADDLE_HEIGHT;
			}
		}

		///////////////////////////////////////////////////
		// This is where the game logic is taken care of //
		///////////////////////////////////////////////////

		// handles the top and the bottom bounce on the screen
		if( ball_y < 0 || ball_y + BALL_WIDTH > 600 )
		{
			ball_Ydelta = -ball_Ydelta;
		}

		// handles the right paddle collisions
		if( ball_x + ( BALL_HEIGHT / 2 ) < PADDLE_WIDTH && ( paddle_y[0] < ball_y + ( BALL_HEIGHT / 2 ) && ball_y  + ( BALL_HEIGHT / 2 ) < paddle_y[0] + PADDLE_HEIGHT ) )
		{
			ball_Xdelta = -ball_Xdelta;
		}

		// handles the left paddle collisions
		if( ball_x + ( BALL_HEIGHT / 2 ) > SCREEN_WIDTH - PADDLE_WIDTH && ( paddle_y[1] < ball_y + ( BALL_HEIGHT / 2 ) && ball_y + ( BALL_HEIGHT / 2 ) < paddle_y[1] + PADDLE_HEIGHT ) )
		{
			ball_Xdelta = -ball_Xdelta;
		}

		////////////////////////////////////////////////
		// This is where the ball movement is updated //
		////////////////////////////////////////////////

		ball_x += ball_Xdelta;
		ball_y += ball_Ydelta;

		///////////////////////////////////////////////////////
		// This is where all game information is copied over //
		// to the gameStatePacket to be sent to the clients  //
		///////////////////////////////////////////////////////

		gameState.ball_x = ball_x;
		gameState.ball_y = ball_y;
		// The paddle_x would be updated here but since it does
		// not ever change i dont change it
		gameState.paddle_y[0] = paddle_y[0];
		gameState.paddle_y[1] = paddle_y[1];

		//////////////////////////////////////////////////
		// This is where the client information is sent //
		//////////////////////////////////////////////////

		//this contiuouly receives the client state

		// clients[0].Receive( gameStatePacket )
		sf::Packet gameStatePacket;
		gameStatePacket << gameState;
		clients[0].Send( gameStatePacket );
	
		// clients[1].Receive( gameStatePacket )
		clients[1].Send( gameStatePacket );
	
		//FPS.Display();
	} // end of while(1) loop
	listener.Close();
	clients[0].Close();
	clients[1].Close();
}